/**
 * 
 */
package due.pc.pcshoot.control;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.input.touch.TouchEvent;
import org.anddev.andengine.opengl.texture.Texture;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;

import due.pc.pcshoot.MainActivity;

import android.content.Context;
import android.util.Log;

/**
 * @author manhhung.vu
 *
 */
public class Objektiv extends Sprite 
{
	//===============================================================/
	//Constants
	//===============================================================/
	public static final int  OBJECTIVE_WIDTH = 64;
	public static final int  OBJECTIVE_HEIGHT = 64;
	public static final String OBJECTIVE_IMAGEPATH = "gfx/objektiv_rot.png";
	
	public static final int TEXTURE_WIDTH = 64;
	public static final int TEXTURE_HEIGHT = 64;
	
	public static final int BOUND_MIN_X = MainActivity.VIEW_X;
	public static final int BOUND_MAX_X = MainActivity.VIEW_X + MainActivity.VIEW_WIDTH;
	public static final int BOUND_MIN_Y = MainActivity.VIEW_Y;
	public static final int BOUND_MAX_Y = MainActivity.VIEW_Y + MainActivity.VIEW_HEIGHT - 100;
	
	
	//===============================================================/
	//Fields
	//===============================================================/
	private boolean mBounded = true;
	private int mBoundMinX, mBoundMinY, mBoundMaxX, mBoundMaxY;
	
	//Pos X & Y im Bounded-Mode,  
	private float mVirtualUnboundX, mVirtualUnboundY;
	
	private IObjectiveLogicHandler mLogicHandler;
	
	//===============================================================/
	//Constructors
	//===============================================================/
	private Objektiv(float pX, float pY, float pWidth, float pHeight,
			int pBoundMinX, int pBoundMaxX, int pBoundMinY, int pBoundMaxY,
			TextureRegion pTextureRegion) 
	{	
		super(pX, pY, pWidth, pHeight, pTextureRegion);
		mVirtualUnboundX = pX;
		mVirtualUnboundY = pY;
		
		mBoundMinX = pBoundMinX;
		mBoundMaxX = pBoundMaxX;
		mBoundMinY = pBoundMinY;
		mBoundMaxY = pBoundMaxY;
	}
	
	//===============================================================/
	//Override Methods
	//===============================================================/
	@Override
	public void setWidth(float pWidth) 
	{
		super.setWidth(pWidth);
		if (isOutOfRight()) setPosition(mBoundMaxX - mWidth, mY);
	}
	
	@Override
	public void setHeight(float pHeight) 
	{
		super.setHeight(pHeight);
		if (isOutOfBottom()) setPosition(mX, mBoundMaxY - mHeight);
	}
	
	@Override
	public void setPosition(float pX, float pY) 
	{
		mVirtualUnboundX = pX; mVirtualUnboundY = pY;
		super.setPosition(adjustX(), adjustY());
		
//		Log.d("ObjektivPOS", "VirX:"+mVirtualUnboundX+", X:"+mX+
//				", VirY:"+mVirtualUnboundY+", Y:"+ mY);
	}
	
	@Override
	public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) 
	{
		this.setPosition(pSceneTouchEvent.getX() - mWidth / 2, 
				pSceneTouchEvent.getY() - mHeight / 2);
		return true;
	}
	
	//===============================================================/
	//Methods
	//===============================================================/
	public boolean isOutOfBound() {
		return isOutOfBottom() || isOutOfLeft() || isOutOfRight() || isOutOfTop();
	}
	
	protected boolean isOutOfLeft() {
		return mVirtualUnboundX < mBoundMinX;
	}
	
	protected boolean isOutOfRight() {
		return mVirtualUnboundX + mWidth > mBoundMaxX;
	}
	
	protected boolean isOutOfTop() {
		return mVirtualUnboundY < mBoundMinY;
	}
	
	protected boolean isOutOfBottom() {
		return mVirtualUnboundY + mHeight > mBoundMaxY;
	}
	
	private float adjustX() 
	{
		if (!isBounded()) return mVirtualUnboundX;
		
		if (isOutOfLeft()) 
		{
			if (mLogicHandler != null) mLogicHandler.onOutOfLeft();
			return mBoundMinX;
		}
		else if (isOutOfRight()) 
		{
			if (mLogicHandler != null) mLogicHandler.onOutOfRight();
			return mBoundMaxX - mWidth;
		}
		
		return mVirtualUnboundX;
	}
	
	private float adjustY()
	{
		if (!isBounded()) return mVirtualUnboundY;
		
		if (isOutOfTop()) 
		{
			if (mLogicHandler != null) mLogicHandler.onOutOfTop();
			return mBoundMinY;
		}
		else if (isOutOfBottom()) 
		{
			if (mLogicHandler != null) mLogicHandler.onOutOfBottom();
			return mBoundMaxY - mHeight;
		}
		
		return mVirtualUnboundY;
	}
	
	//===============================================================/
	//Getters & Setters
	//===============================================================/
	public void setBounded(boolean pBound) {
		mBounded = pBound;
	}
	
	public boolean isBounded() {
		return mBounded;
	}
	
	public void setLogicHandler(IObjectiveLogicHandler pLogicHandler)
	{
		mLogicHandler = pLogicHandler;
	}
	
	//===============================================================/
	//Static Methods
	//===============================================================/	
	public static Objektiv createObjective(float pX, float pY, Engine pEngine, Context pContext) 
	{
		return creaateObjective(
				pX, pY, OBJECTIVE_WIDTH, OBJECTIVE_HEIGHT,
				BOUND_MIN_X, BOUND_MAX_X, BOUND_MIN_Y, BOUND_MAX_Y,
				pEngine, pContext);
	}
	
	public static Objektiv creaateObjective(
			float pX, float pY, 
			float pWidth, float pHeight,
			int pBoundMinX, int pBoundMaxX, int pBoundMinY, int pBoundMaxY,
			Engine pEngine, Context pContext) 
	{
		Texture texture = new Texture(TEXTURE_WIDTH, TEXTURE_HEIGHT, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		TextureRegion textureRegion = TextureRegionFactory.createFromAsset(texture, pContext, OBJECTIVE_IMAGEPATH, 0, 0);
		pEngine.getTextureManager().loadTexture(texture);
		
		return new Objektiv(pX, pY, pWidth, pHeight, pBoundMinX, pBoundMaxX, pBoundMinY, pBoundMaxY, textureRegion);
	}
	
	
	public static interface IObjectiveLogicHandler 
	{
		public void onOutOfLeft();
		public void onOutOfRight();
		public void onOutOfTop();
		public void onOutOfBottom();
	}
}
